import axios from 'axios'
// 导入 Element 提供的 Message 组件
import { Message } from 'element-ui'
// 导入 store 模块
import store from '@/store'
import router from '@/router'

// 创建 axios 实例
const service = axios.create({
  // process 是 Node 的全局变量，提供了当前 Node.js 进程的信息
  // process.env 属性返回一个包含用户环境信息的对象
  // process.env.VUE_APP_BASE_API 是我们自己配置的一个变量，代表的是则是我们配置的项目的根域名

  // 这个变量模板作者已经帮助我们配置了，在哪里配置的呢 ？
  // 在项目的根目录下有两个 .env 开头的文件，

  // Vue-cli 是基于谁来开发 ？ 对 webpack 进行了封装，都是基于 Node 来运行的
  // 当我们运行 npm run dev 的时候，实际是通过 Node 来解析、运行项目的代码(通过 webpack)
  // 当运行 npm run dev 的时候，是运行开发环境，vue-cli 就自带一个全局的变量 (development)
  // node 通过本身的属性能够获取到 vue-cli 中的 development 属性，从而判断是否是 开发环境
  // 如果是开发环境，就会去找到项目根目录下面的 .ent.development 这个文件，从而解析、获取其他的代码

  // 在项目的根目录下还有一个 .env.production 这个文件，这个文件是运行打包的时候才会执行
  // 当运行 npm run build 的时候，vue-cli 也自带了一个属性 (production)
  // node 通过本身的属性能够获取到 vue-cli 中的 production 属性，从而判断是否是生产环境
  // 如果是生产环境，就会解析 .env.production
  baseURL: process.env.VUE_APP_BASE_API, // 请求基准路径
  // baseURL: 'http://ihrm-java.itheima.net',
  timeout: 5000 // 请求超时的设置，如果过了 5 秒，服务器没有响应，就会报错误
})

// 添加请求拦截器
service.interceptors.request.use((config) => {
  // 先从 vuex 中获取到 token
  const token = store.state.user.token
  // 判断 token 是否存在
  // 如果存在，给请求头统一设置即可
  if (token) {
    config.headers['Authorization'] = `Bearer ${token}`
  }

  // 在发送请求之前做些什么
  return config
}, function(error) {
  // 对请求错误做些什么
  return Promise.reject(error)
})

// 添加响应拦截器
service.interceptors.response.use((response) => { // 响应状态2xx, 3xx进这里
  // 如果 success 为 true，说明请求成功，如果成功，直接把数据返回即可
  if (response.data.success) {
    return response.data
  } else {
    // 如果 success 为 false，说明请求失败，需要将错误结果抛出
    // 如果 success 为 false，我们在此处统一进行错误提示
    Message({
      message: response.data.message,
      type: 'error'
    })

    return Promise.reject(new Error(response.data.message))
  }
}, async(error) => { // 响应状态码为4xx, 5xx开头进这里
  // error是axios内部封装错误对象(不是数据对象)
  // error.response.data -> 后台返回的数据对象
  // console.dir()专门打印对象的详细属性和值(特别Error对象)
  // error.reponse假如为null, 继续error.response.data (知识点: null/undefined读.任何属性都报错, 会终止代码往下执行)
  // 多重验证，保证程序的健壮性(防止null值读属性)
  // && 前面有值代码才会往后执行, 前面如果直接是null/undefined/0/''终止往后执行
  if (error.response && error.response.data && error.response.data.code === 10002) {
    // token过期(被动退出登录状态):(和退出登录一样)
    // 清除用户信息、token
    await store.dispatch('user/logout')
    // 跳转到登录页面
    router.push('/login')
    // 给用户提示
    Message({
      message: '令牌失效，请重新登录',
      type: 'error'
    })
  }
  return Promise.reject(error)
})

export default service
